// License Notification
//======================================================
// Copyright (c) 2010 Channel Intelligence Inc.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// ======================================================


using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace CIP4.RulesEngine
{
    public abstract class ExpressionType : CIValueType
    {

        protected OperandsList m_Operands;
        public OperandsList Operands
        {
            get
            {
                if (m_Operands == null)
                    m_Operands = new OperandsList(this);
                return m_Operands;
            }
        }

        public override bool IsLiteral
        {
            get { return false; }
        }

        public override bool IsNamedValue
        {
            get { return false; }
        }

        protected ExpressionType()
        {
        }

        protected ExpressionType(XElement element)
        {
            // Watch out for LogicalExpressionType(XElement element) as it by-passes this 
            // construction code - any code you put here must be duplicated in LogicalExpressionType(XElement element) 
            // Moan, moan, whine, whine all you like - I wanted LogicalExpression to be a BooleanExpression without
            // having to introduce an otherwise pointless class
            var query = from e in element.Elements()
                        where e.Name.NamespaceName == RuleXmlNS
                        select e;
            foreach (XElement operandElement in query)
                Operands.Add(Initialize(operandElement));
        }

        /// <summary>
        /// For an explanation of how to use this see the comment on ActionType.ResolveName
        /// </summary>
        /// <param name="qualifiedName"></param>
        public override void ResolveName(string qualifiedName)
        {
            foreach (CIValueType operand in Operands)
                operand.ResolveName(qualifiedName);
        }
    }

    public class OperandsList : IList<CIValueType>
    {
        private List<CIValueType> _operands;

        public List<CIValueType> Operands
        {
            get 
            {
                if (_operands == null)
                    _operands = new List<CIValueType>();
                return _operands; 
            }
        }

        readonly ExpressionType _owner;

        public OperandsList(ExpressionType owner)
        {
            _owner = owner;
        }

        public void SetOperands(List<CIValueType> operands)
        {
            _operands = operands;
        }

        #region IList<CIValueType> Members

        public int IndexOf(CIValueType item)
        {
            return Operands.IndexOf(item);
        }

        public void Insert(int index, CIValueType item)
        {
            item.Parent = _owner;
            Operands.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            Operands[index].Parent = null;
        }

        public CIValueType this[int index]
        {
            get
            {
                return Operands[index];
            }
            set
            {
                Operands[index].Parent = null;
                value.Parent = _owner;
                Operands.Remove(value);
                Operands[index] = value;
            }
        }

        #endregion

        #region ICollection<CIValueType> Members

        public void Add(CIValueType item)
        {
            if (!Operands.Contains(item))
                Operands.Add(item);
            item.Parent = _owner;
        }

        public void Clear()
        {
            foreach (CIValueType val in Operands)
                val.Parent = null;
        }

        public bool Contains(CIValueType item)
        {
            return Operands.Contains(item);
        }

        public void CopyTo(CIValueType[] array, int arrayIndex)
        {
            Operands.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return Operands.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(CIValueType item)
        {
            item.Parent = null;
            return true;
        }

        #endregion

        #region IEnumerable<CIValueType> Members

        public IEnumerator<CIValueType> GetEnumerator()
        {
            return Operands.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Operands.GetEnumerator();
        }

        #endregion
    }
}
